package org.example.httpserver.weChatSocket;

import com.alibaba.fastjson.JSONObject;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import lombok.extern.slf4j.Slf4j;
import org.example.httpserver.entity.ImageMessage;
import org.example.httpserver.entity.JoinInfo;
import org.example.httpserver.entity.MessageInfo;
import org.example.httpserver.service.WechatLoginService;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

@Slf4j
@Component
public class weChatSocketService {

    //客户端映射
    private static Map<String, SocketIOClient> clientMap = new HashMap<>();

    //人员名字映射
    private static Map<String, String> nameMap = new HashMap<>();

    //群名称与群成员映射
    private static Map<String, Map<String, String>> groupMap = new HashMap<>();

    private final WechatLoginService wechatLoginService;

    public weChatSocketService(WechatLoginService wechatLoginService) {
        this.wechatLoginService = wechatLoginService;
    }


    @OnConnect
    public void onConnect(SocketIOClient client) {
        clientMap.put(client.getSessionId().toString(), client);
        log.info("客户端：{} sessionId:{}", client.getRemoteAddress().toString(), client.getSessionId());
    }

    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        String sessionId = client.getSessionId().toString();
        log.info("客户端：{}断开连接", sessionId);
        for (Map.Entry<String, SocketIOClient> item : clientMap.entrySet()) {
            if(!sessionId.equals(item.getKey())){
                item.getValue().sendEvent("friend_offline",nameMap.get(sessionId));
            }
        }
        for (Map.Entry<String, SocketIOClient> item : clientMap.entrySet()) {
            if(sessionId.equals(item.getKey())){
                clientMap.remove(item.getKey());
            }
        }

        for (Map.Entry<String, Map<String, String>> group : groupMap.entrySet()) {
            group.getValue().remove(sessionId);
        }
        nameMap.remove(sessionId);
    }

    @OnEvent("send_text")
    public void onSendText(SocketIOClient client, String message) {
        log.info("Message received: {}", message);
        client.sendEvent("receive_text", "Server received message:" + message);
    }

    @OnEvent("send_image")
    public void onSendImage(SocketIOClient client, JSONObject json) {
        log.info("Message received: {}", json);
        client.sendEvent("receive_image", json);
    }

    @OnEvent("loginByUsername")
    public void onLoginByUsername(SocketIOClient client, String username) {
        log.info("Client loginByUsername: {}", username);
        log.info("LoginByUsername received: {}", username);
        //根据username查询数据库
        int res = wechatLoginService.loginByUsername(username);
        client.sendEvent("res_login", res);
    }

    @OnEvent("get_image")
    public void onGetImage(SocketIOClient client, String username) {
        log.info("Client getImage: {}", username);
        //根据username查询数据库找到图像
        String url = wechatLoginService.getImageByUsername(username);
        client.sendEvent("return_image", url);
    }

    //添加我已上线的监听事件

    @OnEvent("self_online")
    public void onSelfOnline(SocketIOClient client, String username) {
        String sessionId = client.getSessionId().toString();
        log.info("{}已上线：{}", sessionId, username);
        //要让所有列表中的人知道,让所有客户端都已知,除了自己
        clientMap.forEach(new BiConsumer<String, SocketIOClient>() {
            @Override
            public void accept(String s, SocketIOClient socketIOClient) {
                if (socketIOClient != client) {
                    socketIOClient.sendEvent("friend_online", username); //告诉所有其他客户端，本客户端上线
                    log.info("friend_online:{}", username);
                    client.sendEvent("friend_online", nameMap.get(socketIOClient.getSessionId().toString())); //告诉本客户端，有哪些人在线
                }


            }
        });
        /*for (Map.Entry<String, SocketIOClient> item : clientMap.entrySet()) {
            item.getValue().sendEvent("friend_online",username); //告诉所有其他客户端，本客户端上线
            log.info("friend_online:{}",username);
            client.sendEvent("friend_online",nameMap.get(item.getKey())); //告诉本客户端，有哪些人在线
        }*/
        nameMap.put(sessionId, username);
    }

    //添加我已下线的监听事件
    @OnEvent("self_offline")
    public void onSelfOffline(SocketIOClient client, String username) {
        String sessionId = client.getSessionId().toString();
        log.info("{}已下线：{}", sessionId, username);
        //让客户端列表中所有的人知道我已下线
        for (Map.Entry<String, SocketIOClient> item : clientMap.entrySet()) {
            item.getValue().sendEvent("friend_offline", username); //告诉所有其他客户端，本客户端下线
        }
        nameMap.remove(sessionId);
    }

    @OnEvent("send_friend_message")
    public void onSendFriendMessage(SocketIOClient client, MessageInfo message) {
        log.info("Message received: {}", message);
        //MessageInfo backMessage = new MessageInfo(message.getTo(), message.getFrom(), message.getContent());
        //拿到message:from to content
        //不包含自己接收 ，从A客户端发到B客户端
        for (Map.Entry<String, String> item : nameMap.entrySet()) {
            if (message.getTo().equals(item.getValue())) {
                clientMap.get(item.getKey()).sendEvent("receive_friend_message", message);
                break;
            }
        }
        //client.sendEvent("receive_friend_message",backMessage);
    }

    @OnEvent("send_friend_image")
    public void onSendFriendImage(SocketIOClient client, ImageMessage message) {
        String sessionId = client.getSessionId().toString();
        log.info("{}发送图片:{}", sessionId, message.toString());
        //log.info("image received: {}", message);
        log.info("getFrom={},getTo={},getName={}", message.getFrom(), message.getTo(), message.getPart().getName());
        for (Map.Entry<String, String> item : nameMap.entrySet()) {
            if (message.getTo().equals(item.getValue())) {
                clientMap.get(item.getKey()).sendEvent("receive_friend_image", message);
                break;
            }
        }

    }

    @OnEvent("join_group")
    public void onJoinGroup(SocketIOClient client, JoinInfo info) {
        String sessionId = client.getSessionId().toString();
        log.info("sessionId:{},info:{}", sessionId, info.toString());
        //让群聊中所有人都知道我进群
        if (!groupMap.containsKey(info.getGroup_name())) {
            groupMap.put(info.getGroup_name(), new HashMap<>());
        }
        //群名称和群成员的映射
        for (Map.Entry<String, Map<String, String>> group : groupMap.entrySet()) {
            log.info("群名称为:{}", group.getKey());
            if (info.getGroup_name().equals(group.getKey())) {
                group.getValue().put(sessionId, info.getUser_name());
                //群成员集合
                for (Map.Entry<String, String> user : group.getValue().entrySet()) {
                    log.info("群成员为:{}", user.getKey());
                    clientMap.get(user.getKey()).sendEvent("person_in_group", info.getUser_name());
                    log.info("{}person_in_group", user.getKey());
                }
                log.info("person_count={}", group.getValue().size());
                client.sendEvent("person_count", group.getValue().size());
            }
        }
    }

    @OnEvent("leave_group")
    public void onLeaveGroup(SocketIOClient client, JoinInfo info) {
        String sessionId = client.getSessionId().toString();
        log.info("{}已退群:{}",sessionId, info.toString());
        //告诉群聊中的所有人(客户端)我退群了
        for (Map.Entry<String, Map<String, String>> group : groupMap.entrySet()) {
            if(info.getGroup_name().equals(group.getKey())){
                group.getValue().remove(sessionId);
                for (Map.Entry<String, String> user : group.getValue().entrySet()) {
                    clientMap.get(user.getKey()).sendEvent("person_out_group",info.getUser_name());
                    log.info("{}person_out_group", user.getKey());
                }
            }
        }
    }

    @OnEvent("send_group_message")
    public void onSendGroupMessage(SocketIOClient client,MessageInfo message){
        String sessionId = client.getSessionId().toString();
        log.info("{}发消息:{}",sessionId,message.toString());
        //把消息发送给群组中的所有客户端
        for (Map.Entry<String, Map<String, String>> group : groupMap.entrySet()) {
            //找到是发送给哪个群
            if(message.getTo().equals(group.getKey())){
                //给群里所有的客户端发送消息,除了自己
                for (Map.Entry<String, String> user : group.getValue().entrySet()) {
                    if(!user.getValue().equals(message.getFrom())){
                        clientMap.get(user.getKey()).sendEvent("receive_group_message",message);
                        log.info("receive_group_message 接收方为"+user.getKey());
                    }
                }
                break;
            }

        }
    }

    @OnEvent("send_group_image")
    public void onSendGroupImage(SocketIOClient client, ImageMessage message){
        String sessionId = client.getSessionId().toString();
        log.info("{}发送了图片数据：{}",sessionId,message.toString());
        //找到图片发送给群中的所有客户端除了自己
        for (Map.Entry<String, Map<String, String>> group : groupMap.entrySet()) {
            //找到需要发送的群
            if(message.getTo().equals(group.getKey())){
                //发送给群中所有的成员除了自己
                for (Map.Entry<String, String> user : group.getValue().entrySet()) {
                    if(!message.getFrom().equals(user.getValue())){
                        clientMap.get(user.getKey()).sendEvent("receive_group_image",message);
                    }
                }
                break;
            }
        }
    }

}
